#include "timestamp.hpp"

#include <dbg.hpp>

int Timestamp::BaseList::calc(uint32_t rtp_ts, uint64_t ms, uint32_t clockrate, uint64_t& pts) {
    // 1. if no base set, set current as base
    if (_bases.empty()) {
        update(rtp_ts, ms);
        pts = ms;
        return 0;
    }

    std::map<uint32_t, Base>::iterator it = _bases.begin();
    std::map<uint32_t, Base>::iterator it_prev = _bases.begin();
    std::map<uint32_t, Base>::iterator it_next = _bases.end();
    while(it->first < rtp_ts && it != _bases.end()) {
        it_prev = it;
        ++it;
    }
    if (it != _bases.end()) {
        it_next = it;
    }
    if (it_next == _bases.end()) {
        it_next = _bases.begin();
    }

    if (it_next->first - rtp_ts < rtp_ts - it_prev->first) {
        pts = it_next->second.clock_ms - (it_next->first - rtp_ts) / (clockrate / 1000);
    } else {
        pts = it_prev->second.clock_ms + (rtp_ts - it_prev->first) / (clockrate / 1000);
    }
    return 0;
}

void Timestamp::BaseList::update(uint32_t rtp_ts, uint64_t ms) {
    Base new_base {rtp_ts, ms};

    _bases.emplace(rtp_ts, new_base);

    return;
}

void Timestamp::BaseList::dump() const {
    for (auto it : _bases) {
        Base& b = it.second;
        dbgd("base ts=%u, ntp=%lu", b.rtp_ts, b.clock_ms);
    }
}

void Timestamp::updateNTP(uint32_t ssrc, uint32_t rtp_ts, uint64_t clock_usec) {
    BaseList& base_list = _base[ssrc];
    base_list.update(rtp_ts, clock_usec/1000);
}

int Timestamp::calculatePts(RTPPacket *p, uint64_t& pts) {
    uint32_t ssrc = p->GetSSRC();
    // workaround rtc-xswitch bug: not restoring rtx ssrc
    if (_base.count(ssrc) == 0 && _base.count(ssrc - 1) == 1) {
        ssrc = ssrc - 1;
    }
    BaseList& base_list = _base[ssrc];
    int ret = base_list.calc(p->GetTimestamp(), p->GetTime(), p->GetClockRate(), pts);
    return ret;
}

void Timestamp::dump() const {
    for (auto it : _base) {
        uint32_t ssrc = it.first;
        BaseList& bl = it.second;
        dbgd("ssrc %u base list:", ssrc);
        bl.dump();
    }
}
